package com.anfeng.cms.service.impl.emp;

import com.anfeng.cms.common.Common;
import com.anfeng.cms.domain.emp.AfEmployeeInfo;
import com.anfeng.cms.domain.emp.AfPostChangeLog;
import com.anfeng.cms.domain.org.AfDepartment;
import com.anfeng.cms.repository.mysql.dao.emp.AfEmployeeInfoMapper;
import com.anfeng.cms.request.emp.EmployeeInfoReq;
import com.anfeng.cms.service.emp.IAfEmployeeInfoService;
import com.anfeng.cms.service.emp.IAfPostChangeLogService;
import com.anfeng.cms.service.org.IAfDepartmentService;
import com.anfeng.cms.util.IdGeneratorUtil;
import com.anfeng.cms.util.JsonMapper;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 吴朋
 * @since 2019-07-15
 */
@Service
@Slf4j
public class AfEmployeeInfoServiceImpl extends ServiceImpl<AfEmployeeInfoMapper, AfEmployeeInfo> implements IAfEmployeeInfoService {

    @Autowired
    private IAfDepartmentService departmentService;

    @Autowired
    private IAfPostChangeLogService postChangeLogService;


    /**
     * 新增员工信息
     *
     * @param employeeInfo 员工信息
     * @return 员工信息
     */
    @Override
    public String addEmployee(AfEmployeeInfo employeeInfo) {
        if (null == employeeInfo) {
            log.error("新增员工信息是吧 传入参数为空");
            return null;
        }
        // 验证是否存在信息
        List<AfEmployeeInfo> employeeInfos = this.getEmployeeInfo(employeeInfo.getEmpNo(), employeeInfo.getMobile(), employeeInfo.getIdentityNo());
        if (null != employeeInfos && !employeeInfos.isEmpty()) {
            log.info("新增员工信息 已经存在相关员工信息 传入参数：{}  已存在信息：{}", JsonMapper.defaultMapper().toJson(employeeInfo),
                    JsonMapper.defaultMapper().toJson(employeeInfos));
            return employeeInfos.get(0).getId();
        }
        String empId = employeeInfo.getId();
        if (StringUtils.isBlank(empId)) {
            empId = IdGeneratorUtil.uuid();
            employeeInfo.setId(empId);
        }
        // 不存在 新增
        employeeInfo.setState(Common.DATA_STATE_NORMAL);
        // 默认使用在职
        employeeInfo.setStatus(Common.EMPLOYEE_STATUS_WORKING);
        Date currentDate = new Date();
        employeeInfo.setCreateTime(currentDate);
        employeeInfo.setModifiedTime(currentDate);
        boolean result = this.insert(employeeInfo);
        if (!result) {
            log.error("新增用户失败 新增信息是：{}", JsonMapper.defaultMapper().toJson(employeeInfo));
            return null;
        }
        return empId;
    }

    /**
     * 更新员工信息
     *
     * @param employeeInfo 员工信息
     * @return 更新状态 -1 失败  1 成功
     */
    @Override
    public int updateEmployeeInfo(AfEmployeeInfo employeeInfo) {
        if (null == employeeInfo || StringUtils.isBlank(employeeInfo.getId())) {
            log.error("更新员工信息 传入参数有误 参数 {}", JsonMapper.defaultMapper().toJson(employeeInfo == null ? "" : employeeInfo));
            return Common.RETURN_FAILED;
        }
        employeeInfo.setModifiedTime(new Date());
        boolean result = this.updateById(employeeInfo);
        if (!result) {
            log.error("更新员工信息失败 员工信息 {}", JsonMapper.defaultMapper().toJson(employeeInfo));
            return Common.RETURN_FAILED;
        }
        return Common.RETURN_SUCCESS;
    }

    /**
     * 根据查询参数获取所有的员工信息
     *
     * @param reqInfo 查询参数
     * @return 员工信息
     */
    @Override
    public List<AfEmployeeInfo> getAllEmployeeInfo(EmployeeInfoReq reqInfo) {
        EntityWrapper<AfEmployeeInfo> wrapper = this.generatorEmployeeWrapper(reqInfo);
        return this.selectList(wrapper);
    }

    /**
     * 根据查询条件获取员工总数
     *
     * @param reqInfo 查询条件
     * @return 查询数量
     */
    @Override
    public int getEmployeeInfoCounts(EmployeeInfoReq reqInfo) {
        EntityWrapper<AfEmployeeInfo> wrapper = this.generatorEmployeeWrapper(reqInfo);
        return this.selectCount(wrapper);
    }

    /**
     * 根据查询条件分页获取员工信息
     *
     * @param reqInfo  查询参数
     * @param page     当前页
     * @param pageSize 每页数量
     * @return 员工信息
     */
    @Override
    public List<AfEmployeeInfo> getEmployeeInfosByPage(EmployeeInfoReq reqInfo, Integer page, Integer pageSize) {
        if (null == page || page < 0) {
            page = 1;
        }
        if (null == pageSize || pageSize < 5) {
            pageSize = 10;
        }
        Page<AfEmployeeInfo> infoPage = new Page<>();
        infoPage.setCurrent(page);
        infoPage.setSize(pageSize);
        infoPage.setAsc(false);
        infoPage.setOrderByField("create_time");

        EntityWrapper<AfEmployeeInfo> wrapper = this.generatorEmployeeWrapper(reqInfo);
        Page<AfEmployeeInfo> employeeInfoPage = this.selectPage(infoPage, wrapper);
        if (null == employeeInfoPage || employeeInfoPage.getRecords() == null || employeeInfoPage.getRecords().isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        return employeeInfoPage.getRecords();
    }

    /**
     * 根据员工编号 手机号 证件号 查询员工信息 主要是为了验证相关信息是否有员工存在  验证信息唯一性
     *
     * @param empNo      员工编号
     * @param mobile     手机号
     * @param identityNo 证件号
     * @return 员工信息
     */
    @Override
    public List<AfEmployeeInfo> getEmployeeInfo(String empNo, String mobile, String identityNo) {
        if (StringUtils.isBlank(empNo) && StringUtils.isBlank(mobile) && StringUtils.isBlank(identityNo)) {
            log.error("根据员工编号：{} 手机号：{} 证件号：{} 查询信息 参数有误", empNo, mobile, identityNo);
            return Collections.EMPTY_LIST;
        }
        AfEmployeeInfo employeeInfo = new AfEmployeeInfo();
        employeeInfo.setState(Common.DATA_STATE_NORMAL);
        EntityWrapper<AfEmployeeInfo> wrapper = new EntityWrapper<>();
        wrapper.setEntity(employeeInfo);
        if (StringUtils.isNotBlank(empNo)) {
            wrapper.and("emp_no = {0}", empNo);
            if (StringUtils.isNotBlank(mobile)) {
                wrapper.or("mobile = {0}", mobile);
                if (StringUtils.isNotBlank(identityNo)) {
                    wrapper.or("identity_no = {0}", identityNo);
                }
            } else {
                if (StringUtils.isNotBlank(identityNo)) {
                    wrapper.or("identity_no = {0}", identityNo);
                }
            }
        } else {
            if (StringUtils.isNotBlank(mobile)) {
                wrapper.and("mobile = {0}", mobile);
                if (StringUtils.isNotBlank(identityNo)) {
                    wrapper.or("identity_no = {0}", identityNo);
                }
            } else {
                if (StringUtils.isNotBlank(identityNo)) {
                    wrapper.and("identity_no = {0}", identityNo);
                }
            }
        }
        return this.selectList(wrapper);
    }

    /**
     * 调整员工部门信息
     *
     * @param empId        员工id
     * @param changeDeptId 新部门id
     * @return 调整结果是否成功 -1 失败 1 成功
     */
    @Override
    public int changeEmployeeDepartmentInfo(String empId, String changeDeptId) {
        if (StringUtils.isBlank(empId) || StringUtils.isBlank(changeDeptId)) {
            log.error("调整员工部门信息 传入参数 不正确 存在空值");
            return Common.RETURN_FAILED;
        }

        // 先获取之前的员工信息
        AfEmployeeInfo employeeInfo = this.selectById(empId);
        if (null == employeeInfo || employeeInfo.getState() == Common.DATA_STATE_DELETE || employeeInfo.getStatus() == Common.EMPLOYEE_STATUS_DIMISSION) {
            log.error("修改员工部门信息失败 员工信息 获取出错 或者 员工信息 禁用 或者 已离职");
            return Common.RETURN_FAILED;
        }
        // 获取部门信息
        AfDepartment departmentInfo = departmentService.getDepartmentInfo(changeDeptId);
        if (null == departmentInfo) {
            log.error("修改员工部门信息 根据部门id {} 新部门信息逻辑删除 或者 不存在", changeDeptId);
            return Common.RETURN_FAILED;
        }
        // 获取之前的部门信息
        AfDepartment preDeptInfo = departmentService.getDepartmentInfo(employeeInfo.getDeptId());
        if (null == preDeptInfo) {
            log.error("修改员工部门信息失败  员工之前的部门信息不存在 或者已经删除");
            return Common.RETURN_FAILED;
        }

        //修改员工部门
        employeeInfo.setDeptId(departmentInfo.getId());
        employeeInfo.setDeptName(departmentInfo.getName());
        employeeInfo.setModifiedTime(new Date());

        boolean update = this.updateById(employeeInfo);
        if (!update) {
            log.error("变更员工部门信息出现失败 修改信息 {}", JsonMapper.defaultMapper().toJson(employeeInfo));
            return Common.RETURN_FAILED;
        }
        //修改成功之后 增加 变更记录
        AfPostChangeLog changeLog = new AfPostChangeLog();
        String changeId = IdGeneratorUtil.uuid();
        changeLog.setId(changeId);

        changeLog.setEmpId(employeeInfo.getId());
        changeLog.setEmpName(employeeInfo.getName());

        changeLog.setBeforeDeptId(preDeptInfo.getId());
        changeLog.setBeforeDeptName(preDeptInfo.getName());
        changeLog.setAfterDeptId(departmentInfo.getId());
        changeLog.setAfterDeptName(departmentInfo.getName());

        changeLog.setBeforeJobId(employeeInfo.getJobId());
        changeLog.setBeforeJobName(employeeInfo.getJobName());
        changeLog.setAfterJobId(employeeInfo.getJobId());
        changeLog.setAfterJobName(employeeInfo.getJobName());

        changeLog.setState(Common.DATA_STATE_NORMAL);
        Date currentDate = new Date();
        changeLog.setCreateTime(currentDate);
        changeLog.setModifiedTime(currentDate);
        // 插入信息
        boolean changeInsert = postChangeLogService.insert(changeLog);
        if (!changeInsert) {
            log.error("调整员工部门 成功 但是 新增变更部门记录失败 员工信息 {}", JsonMapper.defaultMapper().toJson(employeeInfo));
            return Common.RETURN_FAILED;
        }
        return Common.RETURN_SUCCESS;
    }

    /**
     * 根据员工证件号 获取用户信息
     *
     * @param identityNo 证件号
     * @return 员工信息
     */
    @Override
    public AfEmployeeInfo getEmployeeInfoByIdentityNo(String identityNo) {
        if (StringUtils.isBlank(identityNo)) {
            log.error("根据证件号获取员工信息失败 传入证件号 为空");
            return null;
        }
        EmployeeInfoReq req = new EmployeeInfoReq();
        req.setIdentityNo(identityNo);
        EntityWrapper<AfEmployeeInfo> wrapper = generatorEmployeeWrapper(req);
        return this.selectOne(wrapper);
    }

    /**
     * 根据员工编号 获取用户信息
     *
     * @param empNo 员工编号
     * @return 员工信息
     */
    @Override
    public AfEmployeeInfo getEmployeeInfoByEmpNo(String empNo) {
        if (StringUtils.isBlank(empNo)) {
            log.error("根据员工编号获取员工信息失败 传入员工编号 为空");
            return null;
        }
        EmployeeInfoReq req = new EmployeeInfoReq();
        req.setEmpNo(empNo);
        EntityWrapper<AfEmployeeInfo> wrapper = generatorEmployeeWrapper(req);
        return this.selectOne(wrapper);
    }

    /**
     * 根据部门id 获取部门下员工的数量
     *
     * @param deptId 部门id
     * @return 员工数量
     */
    @Override
    public int getDepartmentEmployeeCount(String deptId) {
        if (StringUtils.isBlank(deptId)) {
            log.error("根据部门id 获取员工数量 传入参数为null");
            return 0;
        }
        List<String> subDepts = this.getAllSubDeptIdsFromDeptId(deptId);
        if (subDepts == null || subDepts.isEmpty()) {
            return 0;
        }
        AfEmployeeInfo afEmployeeInfo = new AfEmployeeInfo();
        afEmployeeInfo.setState(Common.DATA_STATE_NORMAL);
        EntityWrapper<AfEmployeeInfo> wrapper = new EntityWrapper<>();
        wrapper.setEntity(afEmployeeInfo);
        wrapper.in("dept_id", subDepts);
        return this.selectCount(wrapper);
    }

    /**
     * 根据部门获取部门下的员工信息
     *
     * @param deptId 部门id
     * @return 员工信息
     */
    @Override
    public List<AfEmployeeInfo> getDepartmentEmployee(String deptId) {
        if (StringUtils.isBlank(deptId)) {
            log.error("根据部门id 获取员工数量 传入参数为null");
            return Collections.EMPTY_LIST;
        }
        List<String> subDepts = this.getAllSubDeptIdsFromDeptId(deptId);
        if (subDepts == null || subDepts.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        AfEmployeeInfo afEmployeeInfo = new AfEmployeeInfo();
        afEmployeeInfo.setState(Common.DATA_STATE_NORMAL);
        EntityWrapper<AfEmployeeInfo> wrapper = new EntityWrapper<>();
        wrapper.setEntity(afEmployeeInfo);
        wrapper.in("dept_id", subDepts);
        return this.selectList(wrapper);
    }

    /**
     * 根据请求参数 生成相应的wrapper
     * @param reqInfo 请求参数
     * @return wrapper
     */
    private EntityWrapper<AfEmployeeInfo> generatorEmployeeWrapper(EmployeeInfoReq reqInfo) {
        if (null == reqInfo) {
            reqInfo = new EmployeeInfoReq();
        }
        AfEmployeeInfo employeeInfo = new AfEmployeeInfo();
        employeeInfo.setDeptId(reqInfo.getDeptId());
        employeeInfo.setEmpNo(reqInfo.getEmpNo());
        employeeInfo.setStatus(reqInfo.getStatus());
        employeeInfo.setMobile(reqInfo.getMobile());
        employeeInfo.setIdentityNo(reqInfo.getIdentityNo());
        employeeInfo.setName(reqInfo.getName());

        EntityWrapper<AfEmployeeInfo> wrapper = new EntityWrapper<>();
        wrapper.setEntity(employeeInfo);
        return wrapper;
    }

    /**
     * 根据部门id 获取其下所有部门的id
     * @param deptId 部门id
     * @return 子部门及部门id
     */
    private List<String> getAllSubDeptIdsFromDeptId(String deptId) {
        List<String> deptIds = new ArrayList<>();
        // 获取部门信息
        AfDepartment department = departmentService.getDepartmentInfo(deptId);
        if (null == department) {
            log.error("未查询到指定部门信息 {}", deptId);
            return deptIds;
        }
        deptIds.add(department.getId());
        List<AfDepartment> departments = departmentService.getSubDepartments(deptId);
        if (null == departments || departments.isEmpty()) {
            return deptIds;
        }

        for (AfDepartment dept : departments) {
            List<String> subs = getAllSubDeptIdsFromDeptId(dept.getId());
            if (subs != null && !subs.isEmpty()) {
                deptIds.addAll(subs);
            }
        }
        return deptIds;
    }

}
